home *** CD-ROM | disk | FTP | other *** search
- /*============================================================
- Exceptions.h
-
- greggor@apple.com
- ============================================================*/
- #ifndef __EXCEPTIONS__
- #define __EXCEPTIONS__
- #define Exceptions_h
-
- #ifndef __RESOURCES__
- #include <Resources.h>
- #endif
-
- #ifndef __MEMORY__
- #include <Memory.h>
- #endif
-
- #include <setjmp.h>
-
- //
- // Our error codes
- //
- const OSErr ePointerNil = -110;
- const OSErr eGeneralErr = -1;
- const OSErr eAssertionFailure = -30000;
- const OSErr eRequirementNotMet = -30001;
- const OSErr eValueOutOfRange = -30002;
- const OSErr eIndexOutOfRange = -30003;
- const OSErr eLinksCorrupt = -30004;
- const OSErr eDataCorrupt = -30005;
- const OSErr eWrongDataType = -30006;
-
- //
- // Constants used by the failure class
- //
- const long kMagicFailID = 'fail';
-
- const long kTryFrameOnFailureStack = 0x0001;
- const long kExceptionThrown = 0x0002;
- const long kTryInProgress = 0x0004;
- const long kTrySucceeded = 0x0008;
- const long kResignalingFailure = 0x0010;
- const long kTryBlockHasBeenSetup = 0x0100;
-
- //
- // Failure class
- //
- class TException
- {
- public:
- TException* fNext;
- OSErr fError;
- long fFlags;
- jmp_buf fEnv;
- long fMagicFailID;
-
- TException() : fNext(nil), fError(noErr), fFlags(0), fMagicFailID(kMagicFailID) {};
- Boolean Setup();
- void TearDown();
- Boolean BeginTry();
- OSErr ExceptionError() { return fError; };
- };
-
- //
- // try / catch macros
- //
- // Formerly, I used the result of setjmp to set status bits;
- // however, that's not working in MetroWerks. My guess is that
- // there is some confusion over sizeof(int), but I'm not sure.
- // Therefore, I'm just going to assume that the second time
- // fi.Setup executes, we're failing.
- //
- #define Try TException fi; setjmp(fi.fEnv); if(fi.Setup()) while(fi.BeginTry())
- #define Catch(err) else if((err = fi.ExceptionError()) != noErr)
-
- typedef void (*NotifyFailureProc)(OSErr err);
-
- //
- // Globals:
- //
- extern TException* gExceptionStack;
-
- //
- // Prototypes
- //
- void Throw(OSErr theErr);
-
- void SetExceptionNotifyProc(NotifyFailureProc notifyProc);
- Boolean ExceptionNotifyProcInstalled(void);
- void NotifyFailure(OSErr err);
-
- void MakeVariableNoRegister( void* foo );
-
- //
- // You really shouldn't use this... far better to say:
- //
- // Catch(err)
- // {
- // Throw(err);
- // }
- //
- #define ResignalFailure() Throw(fi.ExceptionError());
-
- //
- // This macro references the address of the specified local
- // variable; this will prevent the compiler from using the
- // variable as a register variable.
- //
- #define NOREGISTER(x) ( MakeVariableNoRegister( (void*)(&(x)) ) )
-
- //
- // Convenience functions
- //
- inline void Fail() { Throw(eGeneralErr); }
- inline void FailErr(OSErr theErr) { if(theErr != noErr) Throw(theErr); }
- inline void FailResError() { FailErr(ResError()); }
- inline void FailMemError() { FailErr(MemError()); }
- inline void FailNil(void* ptr) { if(ptr == nil) Throw(ePointerNil); }
- inline void FailResErrorOrNil(void* ptr) { FailResError(); FailNil(ptr); }
- inline void FailMemErrorOrNil(void* ptr) { FailMemError(); FailNil(ptr); }
-
- //
- // Requirements
- //
- inline void Require(Boolean truth) { if( !(truth) ) Throw(eRequirementNotMet); }
- inline void RequirePtrValid(void* p) { if( (p == nil) || (((long)(p) & 1) != 0) ) Throw(eRequirementNotMet); }
- inline void RequireHandleValid(Handle h) { RequirePtrValid((void*)(h)); RequirePtrValid((void*)(*h)); }
-
- //
- // Requirements must always be met, but Assertions can be removed in non-debug builds
- // as they are statements that are ASSUMED to always be true
- //
- inline void Assert(Boolean truth) { if( !(truth) ) Throw(eAssertionFailure); }
- inline void AssertPtrValid(void* p) { if( (p == nil) || (((long)(p) & 1) != 0) ) Throw(eAssertionFailure); }
- inline void AssertHandleValid(void** h) { AssertPtrValid((void*)h); AssertPtrValid(*h); }
-
- #define ASSERT(x) Assert(x)
- #define REQUIRE(x) Require(x)
-
- #endif
-